package mysql

import (
	"core/utils"
	"errors"

	"github.com/go-xorm/builder"
	"github.com/go-xorm/xorm"
)

var NotFound = errors.New("not found")

type Cond struct {
	Cond  builder.Cond
	Start int
	Limit int
	Asc   string
	Desc  string
	Cols  []string
}

type Session struct {
	*xorm.Session
}

func NewSession() *Session {
	return &Session{X.NewSession()}
}

// cond可以为nil，cond.cond也可以为nil
func FindList(data interface{}, cond *Cond) (count int64, err error) {
	if cond == nil {
		cond = new(Cond)
	}
	var session *xorm.Session
	if cond.Desc != "" {
		session = X.Desc(cond.Desc)
	}
	if cond.Asc != "" {
		session = X.Asc(cond.Asc)
	}
	if cond.Desc == "" && cond.Asc == "" {
		session = X.Asc("id")
	}

	if cond.Limit > 0 {
		session = session.Limit(cond.Limit, cond.Start)
	}
	if cond.Cond != nil {
		session = session.Where(cond.Cond)
	}
	if len(cond.Cols) > 0 {
		session = session.Cols(cond.Cols...)
	}

	count, err = session.FindAndCount(data)
	return
}

func Load(data interface{}) (err error) {
	found, err := X.Get(data)
	if err != nil {
		return
	}
	if !found {
		return NotFound
	}
	return
}

func Create(data ...interface{}) (err error) {
	count, err := X.Insert(data...)
	if err != nil {
		return
	}
	if count == 0 {
		return NotFound
	}
	return
}

// data 必须为指针
func Update(id int64, data interface{}) (err error) {
	count, err := X.ID(id).Update(data)
	if err != nil {
		return
	}
	if count == 0 {
		return NotFound
	}
	return
}

// data 必须为指针
func UpdateCol(id int64, data interface{}, cols ...string) (err error) {
	count, err := X.ID(id).Cols(cols...).Update(data)
	if err != nil {
		return
	}
	if count == 0 {
		return NotFound
	}
	return
}

// data 必须为指针
func UpdateAll(id int64, data interface{}) (err error) {
	count, err := X.ID(id).AllCols().Update(data)
	if err != nil {
		return
	}
	if count == 0 {
		return NotFound
	}
	return
}

// data 传指针
func Save(id int64, data interface{}) (err error) {
	//exist, err := X.Table("pic_upload_mysql").Exist(&builder.Eq{"id": id})
	exist, err := X.Table(data).Where("id = ?", id).Exist()
	utils.Info(exist, err, id)
	if exist {
		_, err = X.ID(id).Update(data)
		if err != nil {
			utils.Error(err)
		}
	} else {
		err = Create(data)
		if err != nil {
			utils.Error(err)
		}
	}
	return
}

func Del(data interface{}) (err error) {
	count, err := X.Delete(data)
	if err != nil {
		return
	}
	if count == 0 {
		return NotFound
	}
	return
}

func (s *Session) FindList(data interface{}, cond *Cond) (count int64, err error) {
	if cond == nil {
		cond = new(Cond)
	}
	if cond.Desc != "" {
		s.Session = s.Desc(cond.Desc)
	}
	if cond.Asc != "" {
		s.Session = s.Asc(cond.Asc)
	}
	if cond.Desc == "" && cond.Asc == "" {
		s.Session = s.Asc("id")
	}

	if cond.Limit > 0 {
		s.Session = s.Limit(cond.Limit, cond.Start)
	}
	if cond.Cond != nil {
		s.Session = s.Where(cond.Cond)
	}
	if len(cond.Cols) > 0 {
		s.Session = s.Cols(cond.Cols...)
	}

	count, err = s.FindAndCount(data)
	return
}

func (s *Session) Load(data interface{}) (err error) {
	found, err := s.Get(data)
	if err != nil {
		return
	}
	if !found {
		return NotFound
	}
	return
}

func (s *Session) Create(data ...interface{}) (err error) {
	count, err := s.Insert(data...)
	if err != nil {
		return
	}
	if count == 0 {
		return NotFound
	}
	return
}

func (s *Session) Update(id int64, data interface{}) (err error) {
	count, err := s.ID(id).Update(data)
	if err != nil {
		return
	}
	if count == 0 {
		return NotFound
	}
	return
}

func (s *Session) Save(id int64, data interface{}) (err error) {
	exist, err := s.Exist(&builder.Eq{"id": id})
	utils.Info(exist, err)
	if exist {
		_, err = s.ID(id).Update(data)
		if err != nil {
			utils.Error(err)
		}
	} else {
		err = s.Create(data)
		if err != nil {
			utils.Error(err)
		}
	}
	return
}

func (s *Session) Del(data interface{}) (err error) {
	count, err := s.Delete(data)
	if err != nil {
		return
	}
	if count == 0 {
		return NotFound
	}
	return
}
